package lk.icta.core.dao.impl;

import lk.icta.common.dao.impl.BaseDAO;
import lk.icta.core.dao.LandAssociationDao;
import lk.icta.core.entity.LandAssociation;
import lk.icta.user.entity.User;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.Query;
import java.util.List;

/**
 * @author Supun Nimesh Karunathilaka
 */
public class LandAssociationDaoImpl extends BaseDAO implements LandAssociationDao {

    @Transactional(propagation = Propagation.MANDATORY)
    public void addLandAlienationMetadata(lk.icta.core.entity.LandAssociation landAssociation, User user) {
        em.persist(landAssociation);
    }

    @Transactional(propagation = Propagation.MANDATORY)
    public void updateLandAlienationMetadata(lk.icta.core.entity.LandAssociation landAssociation, User user) {
        em.merge(landAssociation);
    }

    @Transactional(propagation = Propagation.NEVER, readOnly = true)
    public List<lk.icta.core.entity.LandAssociation> getAllAlienationMethodMetadataByLand(long id, User user) {
        Query q = em.createNamedQuery("getAllAlienationMethodMetadataByLand");
        q.setParameter("id", id);
        return (q.getResultList().size() > 0) ? q.getResultList() : null;
    }

    @Transactional(propagation = Propagation.NEVER, readOnly = true)
    public List<lk.icta.core.entity.LandAssociation> getAllNotApprovedDefineAlienationMethodMetadata(User user) {
        Query q = em.createNamedQuery("getAllNotApprovedDefineAlienationMetadata");
        return (q.getResultList().size() > 0) ? q.getResultList() : null;
    }

    @Transactional(propagation = Propagation.NEVER, readOnly = true)
    public List<lk.icta.core.entity.LandAssociation> getAllNotApprovedDefineAlienationMetadataByUser(User user) {
        Query q = em.createNamedQuery("getAllNotApprovedDefineAlienationMetadataByUser");
        populateDsDivisionList(q, user);
        return (q.getResultList().size() > 0) ? q.getResultList() : null;
    }

    @Transactional(propagation = Propagation.NEVER, readOnly = true)
    public List<lk.icta.core.entity.LandAssociation> getAllNotApprovedDefineAlienationMetadataByGn(int id,User user) {
        Query q = em.createNamedQuery("getAllNotApprovedDefineAlienationMetadataByGn");
        q.setParameter("gnId", id);
        return (q.getResultList().size() > 0) ? q.getResultList() : null;
    }

    @Transactional(propagation = Propagation.NEVER, readOnly = true)
    public List<lk.icta.core.entity.LandAssociation> getAllNotApprovedAssociationAlienationMethodMetadata(User user) {
        Query q = em.createNamedQuery("getAllNotApprovedAssociationAlienationMethodMetadata");
        return (q.getResultList().size() > 0) ? q.getResultList() : null;
    }

    @Transactional(propagation = Propagation.NEVER, readOnly = true)
    public List<lk.icta.core.entity.LandAssociation> getAllNotApprovedAssociationAlienationMethodMetadataByUser(User user) {
        Query q = em.createNamedQuery("getAllNotApprovedAssociationAlienationMethodMetadataByUser");
        populateDsDivisionList(q, user);
        return (q.getResultList().size() > 0) ? q.getResultList() : null;
    }

    @Transactional(propagation = Propagation.NEVER, readOnly = true)
    public List<lk.icta.core.entity.LandAssociation> getAllNotApprovedAssociationAlienationMethodMetadataByGn(int id,User user) {
        Query q = em.createNamedQuery("getAllNotApprovedAssociationAlienationMethodMetadataByGn");
        q.setParameter("gnId", id);
        return (q.getResultList().size() > 0) ? q.getResultList() : null;
    }

    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public lk.icta.core.entity.LandAssociation getAlienationMethodMetadataById(long id, User user) {
        Query q = em.createNamedQuery("getAlienationMethodMetadataById");
        q.setParameter("id", id);
        return (lk.icta.core.entity.LandAssociation) q.getSingleResult();
    }

    @Transactional(propagation = Propagation.NEVER, readOnly = true)
    public List<lk.icta.core.entity.LandAssociation> getAllNotApprovedAlienationMethodMetadataByLand(long id, User user) {
        Query q = em.createNamedQuery("getAllNotApprovedAlienationMethodMetadataByLand");
        q.setParameter("id", id);
        return (q.getResultList().size() > 0) ? q.getResultList() : null;
    }

    @Transactional(propagation = Propagation.NEVER, readOnly = true)
    public List<lk.icta.core.entity.LandAssociation> getAllNotApprovedDefineAlienationMethodMetadataByLand(long id, User user) {
        Query q = em.createNamedQuery("getAllNotApprovedDefineAlienationMethodMetadataByLand");
        q.setParameter("id", id);
        return (q.getResultList().size() > 0) ? q.getResultList() : null;
    }

    @Transactional(propagation = Propagation.NEVER, readOnly = true)
    public List<lk.icta.core.entity.LandAssociation> getAlienationMethodMetadataListByLand(long id, User user) {
        Query q = em.createNamedQuery("getAlienationMethodMetadataListByLand");
        q.setParameter("id", id);
        return (q.getResultList().size() > 0) ? q.getResultList() : null;
    }

    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public lk.icta.core.entity.LandAssociation getAlienationMethodMetadataByLand(long id, User user) {
        Query q = em.createNamedQuery("getAlienationMethodMetadataListByLand");
        q.setParameter("id", id);
        if (q.getResultList().size() > 0) {
            return (lk.icta.core.entity.LandAssociation) q.getResultList().get(0);
        } else {
            return null;
        }
    }

    @Transactional(propagation = Propagation.NEVER, readOnly = true)
    public List<lk.icta.core.entity.LandAssociation> getAllAlienationMethodMetadataByAlienationMethod(int id, User user) {
        Query q = em.createNamedQuery("getAllAlienationMethodMetadataByAlienationMethod");
        q.setParameter("id", id);
        return (q.getResultList().size() > 0) ? q.getResultList() : null;
    }

    @Transactional(propagation = Propagation.NEVER, readOnly = true)
    public List<lk.icta.core.entity.LandAssociation> getAllApprovedDefineAlienationMethodMetadataByUser(User user) {
        Query q = em.createNamedQuery("getAllApprovedDefineAlienationMethodMetadataByUser");
        populateDsDivisionList(q, user);
        return (q.getResultList().size() > 0) ? q.getResultList() : null;
    }

    @Transactional(propagation = Propagation.NEVER, readOnly = true)
    public List<lk.icta.core.entity.LandAssociation> getAllApprovedDefineAlienationMethodMetadataByUserAndMethodId(int id,User user) {
        Query q = em.createNamedQuery("getAllApprovedDefineAlienationMethodMetadataByUserAndMethodId");
        q.setParameter("id", id);
        populateDsDivisionList(q, user);
        return (q.getResultList().size() > 0) ? q.getResultList() : null;
    }

    @Transactional(propagation = Propagation.NEVER, readOnly = true)
    public List<lk.icta.core.entity.LandAssociation> getAllApprovedDefineAlienationMethodMetadataByDs(int dsId,User user) {
        Query q = em.createNamedQuery("getAllApprovedDefineAlienationMethodMetadataByDs");
        q.setParameter("dsId", dsId);
        return (q.getResultList().size() > 0) ? q.getResultList() : null;
    }

    @Transactional(propagation = Propagation.NEVER, readOnly = true)
    public List<lk.icta.core.entity.LandAssociation> getAllApprovedDefineAlienationMethodMetadataByDistrict(int districtId,User user) {
        Query q = em.createNamedQuery("getAllApprovedDefineAlienationMethodMetadataByDistrict");
        q.setParameter("districtId", districtId);
        return (q.getResultList().size() > 0) ? q.getResultList() : null;
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    public void removeLandAssociation(long id,User user){
       em.remove(em.find(LandAssociation.class,id));
    }

    private void populateDsDivisionList(Query q, User user) {

        if (user.getDsDivisions() != null && user.getDsDivisions().size() != 0) {
            //for orlp and lcg, find all apps, ignore DS filter
            logger.debug("ds div list size : {}", user.getDsDivisions().size());
            q.setParameter("ignoreDS", 0);
            q.setParameter("DSList", user.getDsDivisions());

        } else {
            q.setParameter("ignoreDS", 1);
            logger.debug("ds div list : {} ignoreDS :{}", user.getDsDivisions(), 1);
            q.setParameter("DSList", null);
        }

    }
}
